/***************************************************************
*
* M3D_FLOAT2INT.H
*
* Float-2-int conversions
***************************************************************/

#pragma once
#define _M3D_FLOAT2INT_H_

#include "ds\ds_const_list.h"

class m3dCONV_FAST {
   float  a, b;
   int    fa, fb;
   float  c1_Int, c2_Int;
   float  c1_Flt, c2_Flt;

public:   
   m3dCONV_FAST(void) : a(0.f), b(0.f), fa(0), fb(0), c1_Int(0.f), c2_Int(0.f), c1_Flt(0.f), c2_Flt(0.f) {}
   m3dCONV_FAST(int _nBit, float _a, float _b) { Init(_nBit, _a, _b); }

   void           Init    (int _nBit, float _a, float _b);
   __INLINE DWORD ConvInt (float t);
   __INLINE float ConvFlt (int t);

   template <class FILE>  void      Write    (FILE& file) const;
   template <class FILE>  void      Read     (FILE& file);
};

class m3dCONV_TIGHT {
   BYTE     nBit;
   WORD     aShort, bShort;
public:
   m3dCONV_TIGHT(void) : nBit(0), aShort(0), bShort(0) {}
   m3dCONV_TIGHT(int _nBit, float _a, float _b) { Init(_nBit, _a, _b); }

   void           Init    (int _nBit, float _a, float _b);
   DWORD          ConvInt (float t);
   float          ConvFlt (int t);

   template <class FILE>  void      Write    (FILE& file) const;
   template <class FILE>  void      Read     (FILE& file);
};

typedef m3dCONV_FAST m3dCONV;

template <class _CONV = m3dCONV_FAST>
class _m3dCONV_POS48 {
protected:
   _CONV  convX17, convY14, convZ17;
public:
   _m3dCONV_POS48();

   void     Init        (void);
   void     Init        (m3dBOX *pBox);

   void     ConvPosTo48 (m3dV *pos, WORD *w1, WORD *w2, WORD *w3);
   void     Conv48ToPos (WORD w1, WORD w2, WORD w3, m3dV *pos);

   template <class FILE>  void      Write    (FILE& file) const;
   template <class FILE>  void      Read     (FILE& file);
};

template <class _CONV = m3dCONV_FAST>
class _m3dCONV_POS32 {
protected:
   _CONV  convX11, convY10, convZ11;
public:
   _m3dCONV_POS32();

   void     Init        (void);
   void     Init        (m3dBOX *pBox);

   void     ConvPosTo32 (m3dV *pos, DWORD *dw);
   void     Conv32ToPos (DWORD dw, m3dV *pos);

   template <class FILE>  void      Write    (FILE& file) const;
   template <class FILE>  void      Read     (FILE& file);
};

typedef _m3dCONV_POS48<m3dCONV_FAST> m3dCONV_POS48;
typedef _m3dCONV_POS32<m3dCONV_FAST> m3dCONV_POS32;

typedef _m3dCONV_POS48<m3dCONV_TIGHT> m3dCONV_POS48_TIGHT;
typedef _m3dCONV_POS32<m3dCONV_TIGHT> m3dCONV_POS32_TIGHT;

/***************************************************************
* m3dCONV_FAST::ConvInt ()
*
***************************************************************/
__INLINE DWORD m3dCONV_FAST::ConvInt (float t) 
{ 
   if (t < a) {
      return fa;
   }
   if (t > b) {
      return fb;
   }
   return (DWORD)(c1_Int + t * c2_Int);
}
/***************************************************************
* m3dCONV_FAST::ConvFlt ()
*
***************************************************************/
__INLINE float m3dCONV_FAST::ConvFlt (int t) 
{ 
   if (t < fa) {
      return a;
   }
   if (t > fb) {
      return b;
   }
   return c1_Flt + t * c2_Flt; 
}



extern DWORD   m3dConvFloatToNBit   (float val, float rangeMin, float rangeMax, int nBit);
extern float   m3dConvNBitToFloat   (DWORD val, int nBit, float rangeMin, float rangeMax);
extern UCHAR   m3dConvFloatTo8      (float val, float rangeMin, float rangeMax);
extern float   m3dConv8ToFloat      (UCHAR val, float rangeMin, float rangeMax);
extern USHORT  m3dConvFloatTo16     (float val, float rangeMin, float rangeMax);
extern float   m3dConv16ToFloat     (USHORT val, float rangeMin, float rangeMax);

extern void m3dConvDirTo16    (m3dV *dir, UCHAR *phiC, UCHAR *thetaC);
extern void m3dConv16ToDir    (UCHAR phiC, UCHAR thetaC, m3dV *dir);
extern void m3dConvDirTo24    (m3dV *dir, UCHAR *b1, UCHAR *b2, UCHAR *b3);
extern void m3dConv24ToDir    (UCHAR b1, UCHAR b2, UCHAR b3, m3dV *dir);
extern void m3dConvVectorTo32 (m3dV *speed, UCHAR *phiC, UCHAR *thetaC, USHORT *lenS);
extern void m3dConv32ToVector (UCHAR phiC, UCHAR thetaC, USHORT lenS, m3dV *speed);
extern void m3dConvPointTo48  (m3dV *pos, WORD *w1, WORD *w2, WORD *w3);
extern void m3dConv48ToPoint  (WORD w1, WORD w2, WORD w3, m3dV *pos);

extern WORD  m3dConvColor888To565 (DWORD colorIn);
extern DWORD m3dConvColor565To888 (WORD colorIn);
extern UCHAR m3dConvColor888To332 (DWORD colorIn);
extern DWORD m3dConvColor332To888 (UCHAR colorIn);

extern void m3dPrepareCompressVert      (const m3dBOX *pBB, ds::ARRAY<INT16, 3> & vertOffset, ds::ARRAY<INT16, 3> & vertScale);
extern void m3dCompressVert             (const INT16 *vertOffset, const INT16 *vertScale, m3dV  *v, INT16 *_v);
extern void m3dCompressVert_4           (const INT16 *vertOffset, const INT16 *vertScale, m3dV *v, INT16 *_v);
extern void m3dDecompressVert           (const INT16 *vertOffset, const INT16 *vertScale, INT16 *v, m3dV  *_v);

extern void m3dCompressTexCoord         (WORD maxTile, m3dVTX *v, INT16  *_v);
extern void m3dCompressTexCoord         (WORD maxTile, m3dVTX *v, INT8   *_v);
extern void m3dDecompressTexCoord       (WORD maxTile, volatile INT16 *v,  m3dVTX *_v);
extern void m3dDecompressTexCoord       (WORD maxTile, INT8  *v,  m3dVTX *_v);

extern void m3dCompressNormal_11_11_10  (const m3dV  *norm, DWORD *_norm);
extern void m3dCompressNormal_10_10_10  (const m3dV  *norm, DWORD *_norm);
extern void m3dCompressNormal           (const m3dV  *norm, BYTE  *_norm);
extern void m3dCompressNormal_FP32      (const m3dV  *norm, float *_norm);
extern void m3dCompressNormal_8_8       (const m3dV  *norm, INT16 *_norm);
extern void m3dDecompressNormal_11_11_10(const DWORD *norm, m3dV  *_norm);
extern void m3dDecompressNormal_10_10_10(const DWORD *norm, m3dV  *_norm);
extern void m3dDecompressNormal         (const BYTE  *norm, m3dV  *_norm);
extern void m3dDecompressNormal_FP32    (const float *norm, m3dV  *_norm);
extern void m3dDecompressNormal_8_8     (const INT16 *norm, m3dV  *_norm);

extern void m3dCompressTangent          (const m4dV  *tang, INT16 *_tang);
extern void m3dDecompressTangent        (const INT16 *tang, m4dV  *_tang);
extern void m3dCompressTangent          (const m4dV  *tang, BYTE  *_tang);
extern void m3dDecompressTangent        (const BYTE  *tang, m4dV  *_tang);

unsigned short floatToHalfI(unsigned i);
unsigned       halfToFloatI(unsigned short y);

extern void mpdrConvDirToInt              (m3dV *dir, UCHAR *phiC, UCHAR *thetaC);
extern void mpdrConvIntToDir              (UCHAR phiC, UCHAR thetaC, m3dV *dir);
extern void mpdrConvDirTo3Byte            (m3dV *dir, UCHAR *b1, UCHAR *b2, UCHAR *b3);
extern void mpdrConv3ByteToDir            (UCHAR b1, UCHAR b2, UCHAR b3, m3dV *dir);
extern void mpdrConvM3DVToIntAngLen       (m3dV *speed, UCHAR *phiC, UCHAR *thetaC, USHORT *lenS);
extern void mpdrConvIntAngLenToM3DV       (UCHAR phiC, UCHAR thetaC, USHORT lenS, m3dV *speed);
extern void mpdrConvIntAngLenToM3DVHiRes  (USHORT phiC, USHORT thetaC, USHORT lenS, m3dV *speed);
extern void mpdrConvM3DVToIntAngLenHiRes  (m3dV *speed, USHORT *phiC, USHORT *thetaC, USHORT *lenS);
extern void mpdrConvM3DVTo3Word           (m3dV *pos, WORD *w1, WORD *w2, WORD *w3);
extern void mpdrConv3WordToM3DV           (WORD w1, WORD w2, WORD w3, m3dV *pos);

/***************************************************************
* float to half
***************************************************************/
inline unsigned short floatToHalf(float i)
{
   union { float f; unsigned i; } v;
   v.f = i;
   return floatToHalfI(v.i);
}

/***************************************************************
* half to float
***************************************************************/
inline float halfToFloat(unsigned short y)
{
   union { float f; unsigned i; } v;
   v.i = halfToFloatI(y);
   return v.f;
}


#include <m3d/m3d_float2int.hpp>

//
// End-of-file M3D_FLOAT2INT.H
//
